package com.project.srtp.common.biz;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.project.srtp.common.result.Results;
import com.project.srtp.common.result.errorcode.ResultCode;
import com.project.srtp.common.utils.JwtTokenProvider;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Collections;
import java.util.List;

@Slf4j
@RequiredArgsConstructor
public class UserTransmitFilter implements Filter {
    private final StringRedisTemplate redisTemplate;
    private final JwtTokenProvider jwtTokenProvider;

    private static final List<String> IGNORE_URI = List.of(
            "/api/user/login",
            "/api/user/register",
            "/api/user/register/**",
            "/doc.html",
            "/webjars/**",
            "/swagger-resources",
            "/v3/api-docs/**"
    );

    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        String requestURI = httpRequest.getRequestURI().substring(httpRequest.getContextPath().length());

        try {
            // 跳过无需认证的路径
            if (shouldSkip(requestURI)) {
                chain.doFilter(request, response);
                return;
            }

            // 1. 从请求头中提取用户信息（由网关透传）
            String userIdHeader = httpRequest.getHeader("X-User-Id");
            String usernameHeader = httpRequest.getHeader("X-Username");
            String rolesHeader = httpRequest.getHeader("X-Roles");

            if (userIdHeader == null || usernameHeader == null) {
                sendError(response, "未提供用户身份信息（请通过网关访问）");
                return;
            }

            // 2. 设置用户上下文
            UserContext context = UserContext.builder()
                    .userId(Long.parseLong(userIdHeader))
                    .username(usernameHeader)
                    .roles(rolesHeader != null ? List.of(rolesHeader.split(",")) : List.of())
                    .build();
            UserContextHolder.setContext(context);

            UsernamePasswordAuthenticationToken authenticationToken =
                    new UsernamePasswordAuthenticationToken(
                            context.getUsername(), null, Collections.emptyList());
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);

            chain.doFilter(request, response);
        } finally {
            UserContextHolder.clear();
        }
    }

    private boolean shouldSkip(String uri) {
        PathMatcher pathMatcher = new AntPathMatcher();
        return IGNORE_URI.stream().anyMatch(pattern -> pathMatcher.match(pattern, uri));
    }

    private void sendError(ServletResponse response, String message) throws IOException {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.setStatus(HttpStatus.UNAUTHORIZED.value());
        httpResponse.setContentType(MediaType.APPLICATION_JSON_VALUE);
        httpResponse.getWriter().write(
                new ObjectMapper().writeValueAsString(
                        Results.error(ResultCode.UNAUTHORIZED, message)
                )
        );
    }
}
